"""
Case Type   : 操作系统类-文件系统故障
Case Name   : gs_om启停时，备机注入故障系统文件句柄耗尽
Create At   : 2021/7/23
Owner       : @peilinqian
Description :
    1、注入文件系统系统文件句柄耗尽故障
    2、备节点上执行gs_om stop 故障清理后gs_om stop成功
    3、注入文件系统系统文件句柄耗尽故障
    4、备节点上执行gs_om start 故障清理后gs_om start成功
Expect      :
    1、故障注入成功
    2、gs_om stop报错“Too many open files” 再次执行成功
    3、故障注入成功
    4、gs_om start报错“Too many open files” 再次执行成功
History     :
    Modified by @peilinqian 2021/8/23: 优化故障清理
    Modified by @peilinqian 2021/12/9: 优化故障清理后重启数据库
    Modified by @peilinqian 2022/4/21: 优化断言 适应结果为None的情况
    Modified by @peilinqian 2024/2/21: 优化用例删除不必要步骤
    Modified by @peilinqian 2024/7/9： 优化用例，增加清理等待时间
"""
import os
import time
import unittest

from testcase.utils.ComThread import ComThread
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.CommonSH import RestartDbCluster
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node


class ReliabilityFileSystem(unittest.TestCase):
    nodes = ("PrimaryDbUser", "Standby1DbUser", "Standby2DbUser")

    @RestartDbCluster(*nodes)
    def setUp(self):
        self.log = Logger()
        self.log.info(f'-----{os.path.basename(__file__)} start-----')
        self.pri_sh = CommonSH(self.nodes[0])
        self.sta_1_sh = CommonSH(self.nodes[1])
        self.sta1_root = Node(node="Standby1Root")
        self.constant = Constant()
        self.com = Common()
        self.inject_time = 60
        self.inject_cmd = f"rfile_deplenish (timeout) values " \
                          f"({self.inject_time})"
        self.check_cmd = "df -h"

    def test_main(self):
        step_txt = '----step1:备节点注入60s句柄耗尽故障; expect:成功----'
        self.log.info(step_txt)
        session = ComThread(self.com.cfe_inject,
                            args=(self.sta1_root,
                                  self.inject_cmd))
        session.setDaemon(True)
        session.start()
        self.start_time = time.time()

        self.log.info("----step2:备节点上执行gs_om stop  expect:失败----")
        result = self.sta_1_sh.stopDbCluster(get_detail=True)
        self.assertIn(self.constant.TOO_MANYY_FILE_MSG, result,
                      "执行失败" + step_txt)
        self.assertNotIn(self.constant.STOP_SUCCESS_MSG, result,
                         "执行失败" + step_txt)

        self.log.info("----step2:主节点上执行gs_om stop  expect:失败----")
        result = self.pri_sh.stopDbCluster(get_detail=True)
        self.assertNotIn(self.constant.STOP_SUCCESS_MSG, result,
                         "执行失败" + step_txt)

        self.log.info("-----注入故障结果-----")
        session.join(60)
        result = session.get_result()
        self.log.info(result)
        self.assertIn(self.constant.SUCCESS_CFE_FULL_FILENUM_MSG, result,
                      "执行失败" + step_txt)
        text = "-----确认故障清理干净-----"
        self.log.info(text)
        while True:
            time.sleep(5)
            check_msg = self.sta1_root.sh(self.check_cmd).result()
            self.log.info(check_msg)
            if self.constant.TOO_MANYY_FILE_MSG not in check_msg:
                break
            end_time = time.time()
            if end_time - self.start_time > self.inject_time * 10:
                break

        self.log.info(
            "----step2:故障清理后主节点上执行gs_om stop expect：成功----")
        result = self.pri_sh.stopDbCluster(get_detail=True)
        self.assertIn(self.constant.STOP_SUCCESS_MSG, result,
                      "执行失败" + step_txt)

        step_txt = '----step3:备节点注入60s句柄耗尽故障; expect:成功----'
        self.log.info(step_txt)
        session = ComThread(self.com.cfe_inject,
                            args=(self.sta1_root,
                                  self.inject_cmd))
        session.setDaemon(True)
        session.start()
        self.start_time = time.time()

        step_txt = '----step4:备节点上执行gs_om start  expect:失败----'
        self.log.info(step_txt)
        result = self.sta_1_sh.startDbCluster(get_detail=True)
        self.assertIn(self.constant.TOO_MANYY_FILE_MSG, result,
                      "执行失败" + step_txt)
        self.assertNotIn(self.constant.START_SUCCESS_MSG, result,
                         "执行失败" + step_txt)

        step_txt = '----step4:主节点上执行gs_om start  expect:失败----'
        self.log.info(step_txt)
        result = self.pri_sh.startDbCluster(get_detail=True)
        self.assertNotIn(self.constant.START_SUCCESS_MSG, result,
                         "执行失败" + step_txt)

        self.log.info("-----注入故障结果-----")
        session.join(60)
        result = session.get_result()
        self.log.info(result)
        self.assertIn(self.constant.SUCCESS_CFE_FULL_FILENUM_MSG, result,
                      "执行失败" + step_txt)
        text = "-----确认故障清理干净-----"
        self.log.info(text)
        while True:
            time.sleep(5)
            check_msg = self.sta1_root.sh(self.check_cmd).result()
            self.log.info(check_msg)
            if self.constant.TOO_MANYY_FILE_MSG not in check_msg:
                break
            end_time = time.time()
            if end_time - self.start_time > self.inject_time * 10:
                break

        step_txt = '----step4:故障清理后备节点上执行gs_om start  expect:成功----'
        self.log.info(step_txt)
        result = self.sta_1_sh.startDbCluster(get_detail=True)
        self.assertNotIn(self.constant.TOO_MANYY_FILE_MSG, result,
                         "执行失败" + step_txt)
        self.assertIn(self.constant.START_SUCCESS_MSG, result,
                      "执行失败" + step_txt)

    def tearDown(self):
        self.log.info("----this is tearDown----")
        text = "-----确认故障清理干净-----"
        self.log.info(text)
        while True:
            time.sleep(5)
            check_msg = self.sta1_root.sh(self.check_cmd).result()
            self.log.info(check_msg)
            if self.constant.TOO_MANYY_FILE_MSG not in check_msg:
                break
            end_time = time.time()
            if end_time - self.start_time > self.inject_time * 10:
                break
        step_txt = '----集群状态异常时，恢复环境----'
        self.log.info(step_txt)
        status = self.pri_sh.getDbClusterStatus("status")
        if not status:
            self.result = self.pri_sh.startDbCluster()
            self.final_status = self.pri_sh.getDbClusterStatus("status")
        self.log.info(f'-----{os.path.basename(__file__)} end-----')
        if not status:
            self.assertIn(self.constant.START_SUCCESS_MSG, self.result,
                          "执行失败" + step_txt)
            self.assertTrue(self.final_status, "执行失败" + step_txt)
